<?php

namespace yifang\db;

class DbManager
{
    /**
     * 数据库连接实例
     * @var array
     */
    protected $instance = [];

    /**
     * 数据库配置
     * @var array
     */
    protected $config = [];

    /**
     * SQL监听
     * @var array
     */
    protected $listen = [];

    /**
     * SQL日志
     * @var array
     */
    protected $dbLog = [];

    /**
     * 查询次数
     * @var int
     */
    protected $queryTimes = 0;

    protected $log;

    /**
     * 初始化配置参数
     * @access public
     * @param array $config 连接配置
     * @return void
     */
    public function setConfig($config)
    {
        $this->config = $config;
    }

    /**
     * 获取配置参数
     * @access public
     * @param string $name    配置参数
     * @param mixed  $default 默认值
     * @return mixed
     */
    public function getConfig($name = '', $default = null)
    {
        if ('' === $name) {
            return $this->config;
        }
        return $this->config[$name] ?? $default;
    }

    /**
     * 获取所有连接实列
     * @access public
     * @return array
     */
    public function getInstance()
    {
        return $this->instance;
    }

    /**
     * 创建/切换数据库连接查询
     * @access public
     * @param string|null $name  连接配置标识
     * @param bool        $force 强制重新连接
     * @return ConnectionInterface
     */
    public function connect($name = null, $force = false)
    {
        return $this->instance($name, $force);
    }

    /**
     * 创建数据库连接实例
     * @access protected
     * @param string|null $name  连接标识
     * @param bool        $force 强制重新连接
     * @return ConnectionInterface
     */
    protected function instance($name = null, $force = false)
    {
        if (empty($name)) {
            $name = $this->getConfig('default_connections', 'mysql');
        }
        if ($force || !isset($this->instance[$name])) {
            $this->instance[$name] = $this->createConnection($name);
        }
        return $this->instance[$name];
    }

    /**
     * 获取连接配置
     * @param string $name
     * @return array
     */
    protected function getConnectionConfig($name)
    {
        $connections = $this->getConfig('connections');
        if (!isset($connections[$name])) {
            throw new \InvalidArgumentException('Undefined db config:' . $name);
        }
        return $connections[$name];
    }

    /**
     * 创建连接
     * @param $name
     * @return ConnectionInterface
     */
    public function getConnection($config)
    {
        $type = !empty($config['type']) ? $config['type'] : 'mysql';
        if (false !== strpos($type, '\\')) {
            $class = $type;
        } else {
            $class = '\\yifang\\db\\connector\\' . ucfirst($type);
        }

        $connection = new $class($config);
        $connection->setDb($this);
        return $connection;
    }

    /**
     * 创建连接
     * @param $name
     * @return ConnectionInterface
     */
    protected function createConnection($name)
    {
        $config = $this->getConnectionConfig($name);
        $type = !empty($config['type']) ? $config['type'] : 'mysql';
        if (false !== strpos($type, '\\')) {
            $class = $type;
        } else {
            $class = '\\yifang\\db\\connector\\' . ucfirst($type);
        }

        /** @var ConnectionInterface $connection */
        $connection = new $class($config);
        $connection->setDb($this);
        return $connection;
    }

    /**
     * 创建连接
     */
    public function connectConfig($name = null,$type,$config)
    {
        if (!isset($this->instance[$name])) {
            if (false !== strpos($type, '\\')) {
                $class = $type;
            } else {
                $class = '\\yifang\\db\\connector\\' . ucfirst($type);
            }

            /** @var ConnectionInterface $connection */
            $connection = new $class($config);
            $connection->setDb($this);
            $this->instance[$name] = $connection;
        }
        return $this->instance[$name];
    }

    /**
     * 更新查询次数
     * @access public
     * @return void
     */
    public function updateQueryTimes()
    {
        $this->queryTimes++;
    }

    /**
     * 重置查询次数
     * @access public
     */
    public function clearQueryTimes()
    {
        $this->queryTimes = 0;
    }

    /**
     * 获得查询次数
     * @access public
     */
    public function getQueryTimes()
    {
        return $this->queryTimes;
    }

    /**
     * 使用表达式设置数据
     * @access public
     * @param string $value 表达式
     * @return Raw
     */
    public function raw($value, array $bind = [])
    {
        return new Raw($value,$bind);
    }

    public function __call($method, $args)
    {
        if(is_callable([$this->connect(), $method])){
            return call_user_func_array([$this->connect(), $method], $args);
        }else{
            throw new \Exception("{$method}不存在",1);
        }
    }
}